package expression;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import runtime.TypeFactory;
import util.Result;
import util.Scope;
import exception.ExpressionException;
import exception.TypeException;
import expression.MultiplicativeExpression.Sign;

/**
 * Klasa odpowiedzialna za przetrzymywanie wyrazenia iloczynu logicznego
 * 
 * @author Jakub Fibinger
 *
 */
public class ConditionalAndExpression extends Expression {
	/**
	 * Ciag wyrazen
	 */
	private List<Expression> expressionList;

	
	/**
	 * @param scope Ciag zakresow zmiennych
	 * @param expressionList Lista wyrazen nizszego poziomu
	 * @throws ExpressionException
	 */
	public ConditionalAndExpression(Scope scope, List<Expression> expressionList)
			throws ExpressionException {
		if (expressionList == null) {
			throw new ExpressionException();
		}
		try {
			if (expressionList.size() != 1) {
				for (Expression el : expressionList) {
					if (!el.getResultType().equals(
							TypeFactory.getInstance().getType("bool"))) {
						throw new ExpressionException();
					}
				}
				result = new Result(TypeFactory.getInstance().getType("bool"),
						null);
			} else {
				result = new Result(expressionList.get(0).getResultType(), null);
			}
			this.expressionList = expressionList;
		} catch (TypeException e) {
			// Zignoruj - nigdy nie wystapi
		}
	}

	/**
	 * @param scope Ciag zakresow zmiennych
	 * @throws ExpressionException
	 */
	public ConditionalAndExpression(Scope scope) throws ExpressionException {
		this(scope, new ArrayList<Expression>());
	}

	/**
	 * @param expression Wyrazenie nizszego poziomu
	 * @throws ExpressionException
	 */
	public void addExpression(Expression expression) throws ExpressionException {
		if (expression == null) {
			throw new ExpressionException();
		}
		if (expressionList.size() >= 1) {
			try {
				if(!expression.getResultType().equals(TypeFactory.getInstance().getType("bool"))) {
					throw new ExpressionException();
				}
				result.setType(TypeFactory.getInstance().getType("bool"));
				expressionList.add(expression);
			} catch (TypeException e) {
				// olac
			}
		} else {
			result.setType(expression.getResultType());
			expressionList.add(expression);
		}
	}

	/* (non-Javadoc)
	 * @see expression.Expression#evaluate()
	 */
	@Override
	public Result evaluate() throws ExpressionException {
		if(this.expressionList.size()==1) {
			result.setValue(expressionList.get(0).evaluate().getValue());
		} else {
			result.setValue(true);
			Iterator<Expression> iterator = expressionList.iterator();
			while (((Boolean) result.getValue()) && iterator.hasNext()) {
				Expression expression = iterator.next();
				result = expression.evaluate();
			}
		}
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString(){
		StringBuilder sb = new StringBuilder("ConditionalAND [ ");
		sb.append(expressionList.get(0) + " ");
		int i = 0;
		for(Expression ex : expressionList)
			if(i++ > 0)
				sb.append( "AND " + ex + " ");
		sb.append("]");
		return sb.toString();
	}
	
}
